package com.kinsin.kinsinutil

import android.os.Handler
import android.os.Looper
import android.util.Log

/**
 * 全局异常拦截
 *
 * 使用示例:
 * NeverCrash
 * .setDebugMode(true)
 * .setMainCrashHandler { thread, ex -> /* 处理主线程异常 */ }
 * .setUncaughtCrashHandler { thread, ex -> /* 处理子线程异常 */ }
 * .register()
 *
 */
object NeverCrash {
    private val TAG = NeverCrash::class.java.simpleName

    private var debugMode = false
    private var mainCrashHandler: MainCrashHandler? = null
    private var uncaughtCrashHandler: UncaughtCrashHandler? = null

    @Synchronized
    fun getMainCrashHandler(): MainCrashHandler {
        return mainCrashHandler ?: MainCrashHandler { _, _ -> }.also {
            mainCrashHandler = it
        }
    }

    /**
     * 主线程异常回调
     */
    fun setMainCrashHandler(handler: MainCrashHandler): NeverCrash {
        mainCrashHandler = handler
        return this
    }

    @Synchronized
    fun getUncaughtCrashHandler(): UncaughtCrashHandler {
        return uncaughtCrashHandler ?: UncaughtCrashHandler { _, _ -> }.also {
            uncaughtCrashHandler = it
        }
    }

    /**
     * 子线程异常回调
     */
    fun setUncaughtCrashHandler(handler: UncaughtCrashHandler): NeverCrash {
        uncaughtCrashHandler = handler
        return this
    }

    /**
     * 设置调试模式
     */
    fun setDebugMode(enable: Boolean): NeverCrash {
        debugMode = enable
        return this
    }

    fun getDebugMode(): Boolean {
        return debugMode
    }

    /**
     * 注册异常监听
     */
    fun register() {
        // 主线程异常拦截
        Handler(Looper.getMainLooper()).post {
            while (true) {
                try {
                    Looper.loop()
                } catch (e: Throwable) {
                    if (debugMode) {
                        Log.e(TAG, "*********************************************************")
                        Log.e(TAG, "*               警告! 有未捕获的主线程异常行为               *")
                        Log.e(TAG, "*======================================================**")
                        Log.e(TAG, "UN CATCH EXCEPTION:", e)
                        Log.e(TAG, "*********************************************************")
                        Log.e(TAG, "\n")
                    }
                    getMainCrashHandler().mainException(Looper.getMainLooper().thread, e)
                }
            }
        }

        // 子线程异常拦截
        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            if (debugMode) {
                Log.e(TAG, "*********************************************************")
                Log.e(TAG, "*               警告! 有未捕获的子线程异常行为               *")
                Log.e(TAG, "*======================================================**")
                Log.e(TAG, "UN CATCH EXCEPTION:", throwable)
                Log.e(TAG, "*********************************************************")
                Log.e(TAG, "\n")
            }
            getUncaughtCrashHandler().uncaughtException(thread, throwable)
        }
    }

    fun interface MainCrashHandler {
        fun mainException(t: Thread, e: Throwable)
    }

    fun interface UncaughtCrashHandler {
        fun uncaughtException(t: Thread, e: Throwable)
    }
}